package io.cici.cc.mybatis.lite.sql_source.scripting.tag;

import io.cici.cc.mybatis.lite.parse.TokenHandler;
import io.cici.cc.mybatis.lite.parse.TokenParser;
import io.cici.cc.mybatis.lite.sql_source.Context;
import io.cici.cc.mybatis.lite.sql_source.scripting.ognl.Ognl;
import io.cici.cc.mybatis.lite.type.SimpleTypeRegistry;


/**
 * @author huihui
 */
public class TextTag implements Tag {
    private final String text;

    public TextTag(String text) {
        this.text = text;
    }

    public boolean hasVariable() {
        VariableCheckTokenParser variableCheckTokenParser = new VariableCheckTokenParser();
        TokenParser tokenParser = createTokenParser(variableCheckTokenParser);
        tokenParser.parse(text);
        return variableCheckTokenParser.isExist();
    }

    @Override
    public boolean apply(Context context) {
        TokenParser tokenParser = createTokenParser(new BindVariableTokenParser(context));
        context.appendSql(tokenParser.parse(text));
        return true;
    }

    private TokenParser createTokenParser(TokenHandler tokenHandler) {
        return new TokenParser("${", "}", tokenHandler);
    }

    private static class VariableCheckTokenParser implements TokenHandler {
        private boolean exist;

        public VariableCheckTokenParser() {
            // Prevent Synthetic Access
        }

        public boolean isExist() {
            return exist;
        }

        @Override
        public String handle(String content) {
            this.exist = true;
            return null;
        }
    }

    private static class BindVariableTokenParser implements TokenHandler {

        private final Context context;


        public BindVariableTokenParser(Context context) {
            this.context = context;

        }

        @Override
        public String handle(String expression) {
            Object parameter = context.getBindings().get("_parameter");
            if (parameter == null) {
                context.getBindings().put("value", null);
            } else if (SimpleTypeRegistry.isSimpleType(parameter.getClass())) {
                context.getBindings().put("value", parameter);
            }
            Object value = Ognl.getValue(context.getBindings(), expression);
            String srtValue = value == null ? "" : String.valueOf(value); // issue #274 return "" instead of "null"

            return srtValue;
        }


    }


}
